package com.kadron.item;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.LinkedList;
import java.util.List;

import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

import com.kadron.basket.KItemBasket;
import com.kadron.common.KConst;
import com.kadron.common.KUtil;
import com.kadron.creator.KCommentModelCreator;
import com.kadron.creator.KItemModelCreator;
import com.kadron.dao.KCommentDAO;
import com.kadron.dao.KDiscountItemDAO;
import com.kadron.dao.KImageDAO;
import com.kadron.dao.KItemColorDAO;
import com.kadron.dao.KItemDAO;
import com.kadron.dao.KItemMaterialDAO;
import com.kadron.dao.KItemSizeDAO;
import com.kadron.dao.KPriceDAO;
import com.kadron.dao.KUserFavoritesDAO;
import com.kadron.dao.KUserImageDAO;
import com.kadron.dao.KVoteDAO;
import com.kadron.datamodel.KCommentDataProvider;
import com.kadron.datamodel.KDataModel;
import com.kadron.entity.Comment;
import com.kadron.entity.Currency;
import com.kadron.entity.ItemColor;
import com.kadron.entity.ItemMaterial;
import com.kadron.entity.ItemSize;
import com.kadron.entity.KItemImage;
import com.kadron.entity.Price;
import com.kadron.entity.User;
import com.kadron.entity.UserFavorites;
import com.kadron.entity.Vote;
import com.kadron.enumeration.CommentType;
import com.kadron.favorites.KFavoriteUserDataProvider;
import com.kadron.favorites.KFavoriteUserModelCreator;
import com.kadron.favorites.KUserFacoriteSearch;
import com.kadron.manager.KSelection;
import com.kadron.service.UserDiscountService;
import com.kadron.service.UserHistoryService;
import com.kadron.session.AbstractCurrencySelector;
import com.kadron.session.Basket;
import com.kadron.session.BasketItem;
import com.kadron.session.KUser;

@AutoCreate
@Name(KItemViewManager.K_NAME)
@Scope(ScopeType.PAGE)
public class KItemViewManager extends AbstractCurrencySelector implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 3618231760842465263L;

	private static final Log log = LogFactory.getLog(KItemViewManager.class);
	
	public static final String K_NAME = "kItemViewManager";
	public static final int STAR_WIDTH = 24;
	
	private KItemModel item; 
	private List<KItemImage> images = new LinkedList<KItemImage>();
	
	private List<ItemColor> colors = new LinkedList<ItemColor>();
	private List<ItemSize> sizes = new LinkedList<ItemSize>();
	private List<ItemMaterial> materials = new LinkedList<ItemMaterial>();
	
	private KDataModel commentList;
	private KCommentDataProvider commentDataProvider;
	
	private Long prevId;
	private Long nextId;
	
	private BigDecimal price;
	private long currencyId;
	
	private boolean voted;
	private boolean favorite;
	private String comment;
	private String name;
	
	private Vote vote;
	
	private BigDecimal rating;
	private int currentRating;
	
	private KItemBasket itemBasket = new KItemBasket();
	private int userDiscount;
	private KDataModel favDataModel;
	private KFavoriteUserDataProvider favoriteUserDataProvider;
	
	@In
	private KItemDAO itemDAO;
	@In
	private KDiscountItemDAO discountItemDAO;
	@In
	private KImageDAO imageDAO;
	@In
	private KUserFavoritesDAO userFavoritesDAO;
	@In
	private KUserImageDAO userImageDAO;
	@In
	private KCommentDAO commentDAO;
	@In
	private KVoteDAO voteDAO;
	@In
	private KPriceDAO priceDAO;
	@In
	private KItemColorDAO itemColorDAO;
	@In
	private KItemMaterialDAO itemMaterialDAO;
	@In
	private KItemSizeDAO itemSizeDAO;
	@In
    private UserHistoryService userHistoryService;
	
	@Create
	public void init() {
		try {			
			Long itemId = (Long) Component.getInstance("itemId");
			KItemModelCreator creator = new KItemModelCreator(itemDAO, discountItemDAO, imageDAO);
			item = creator.create(itemId);
			favoriteUserDataProvider = new KFavoriteUserDataProvider(new KFavoriteUserModelCreator(userFavoritesDAO, userImageDAO), new KUserFacoriteSearch(0, item.getId()), userFavoritesDAO);
			commentDataProvider = new KCommentDataProvider(new KCommentModelCreator(userImageDAO,imageDAO,commentDAO), item.getId(), commentDAO);
			images = imageDAO.getItemImages(itemId);
			KUser kUser = KUser.instance();
			currencyId = kUser.getCurrency().getId();
			doPriceData();
			loadP(item.getItem().getId());
			BigDecimal discountPrice = UserDiscountService.getDiscountPrice(item.getDiscount(), userDiscount, price);
			discountPrice = discountPrice.setScale(2, RoundingMode.HALF_UP);
			item.setDiscountPrice(discountPrice);
			if (kUser.getUser() != null) {
				userDiscount = UserDiscountService.getDiscount(kUser.getUser());				
				BigDecimal yourPrice = UserDiscountService.getYourPrice(userDiscount, discountPrice);
				yourPrice = yourPrice.setScale(2, RoundingMode.HALF_UP);
				item.setYourPrice(yourPrice);
				favorite = userFavoritesDAO.isFavorite(kUser.getUser().getId(), itemId);
			}
			resetComment();
			loadComments();
			Number avgScore = voteDAO.getItemAvgScore(itemId);
			if (avgScore != null) {
				rating = new BigDecimal(avgScore.doubleValue());
				rating = rating.setScale(2, RoundingMode.HALF_UP);
				
				BigDecimal calcRtn = new BigDecimal(avgScore.doubleValue());
				BigDecimal starWidth = new BigDecimal(STAR_WIDTH);
				
				calcRtn = calcRtn.multiply(starWidth);
				calcRtn = calcRtn.setScale(0, RoundingMode.HALF_UP);
				
				currentRating = calcRtn.intValue();
			}
			if (kUser.getUser() != null) {				
				voted = voteDAO.voted(kUser.getUser().getId(), itemId);
			}
			searchFav();
		} catch (Exception e) {
			e.printStackTrace();
			super.setError(true);
		}
	}
	
	public void searchFav() {
		favDataModel = new KDataModel(favoriteUserDataProvider);		
	}
	
	private void loadComments() {
		commentList = new KDataModel(commentDataProvider);
	}
	
	private void resetComment() {
		this.comment = null;
		this.name = null;
	}
	
	private void doPriceData() {
		Price iPrice = priceDAO.find(item.getItem().getId(), currencyId);
		if (iPrice != null && iPrice.getPrice() > 0) {
			price = new BigDecimal(iPrice.getPrice());			
		} else {
			price = null;
		}
		item.setPrice(price);
		BigDecimal discountPrice = UserDiscountService.getDiscountPrice(item.getDiscount(), userDiscount, price);
		discountPrice = discountPrice.setScale(2, RoundingMode.HALF_UP);
		item.setDiscountPrice(discountPrice);
		KUser kUser = KUser.instance();
		if (kUser.getUser() != null) {
			userDiscount = UserDiscountService.getDiscount(kUser.getUser());				
			BigDecimal yourPrice = UserDiscountService.getYourPrice(userDiscount, discountPrice);
			yourPrice = yourPrice.setScale(2, RoundingMode.HALF_UP);
			item.setYourPrice(yourPrice);
			favorite = userFavoritesDAO.isFavorite(kUser.getUser().getId(), item.getId());
		}
		prevId = itemDAO.getPrevNext(item.getId(),currencyId, true);
		nextId = itemDAO.getPrevNext(item.getId(),currencyId, false);		
	}
	
	private void loadP(long itemId) {
		colors = itemColorDAO.getItemColor(itemId);
		if (!colors.isEmpty()) {
			itemBasket.setItemColor(colors.get(0));
		}
		sizes = itemSizeDAO.getItemSize(itemId);
		if (!sizes.isEmpty()) {
			itemBasket.setItemSize(sizes.get(0));
		}
		materials = itemMaterialDAO.getItemMaterial(itemId);
	}
	
	public String basket() {
		if (item == null) {
			bad(KConst.BAD_THING);
			return null;
		}
		if (log.isDebugEnabled()) {
			log.debug("BASKET Item itemId="+item.getId());
		}
		good();
		return null;
	}
	
	public String prevnext(Boolean prev) {
		if (prev == null) {
			bad(KConst.BAD_THING);
			return null;
		}
		KSelection kselection = (KSelection) Component.getInstance("kSelection");
		kselection.setItemId(prev ? prevId : nextId);
		return "k_item";
	}

	public KItemModel getItem() {
		return item;
	}

	public List<KItemImage> getImages() {
		return images;
	}

	public void setImages(List<KItemImage> images) {
		this.images = images;
	}

	public void mainImg(KItemImage img) {
		imageDAO.updateItemImageNotMain(img.getItemId());
		img.setMain(true);
		imageDAO.update(img);
		loadP(item.getId());
		loadImages();
		good();
	}
	
	public void addComment() {
		try {			
			HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
			String ipAddress = request.getRemoteAddr();
			if (KUtil.isEmpty(ipAddress)) {
				bad(KConst.BAD_THING);
				return;
			}
			Comment newcomment = new Comment(CommentType.ITEM, name, comment);
			newcomment.setIpAddress(ipAddress);
			newcomment.setItem(item.getItem());
			User user = KUser.instance().getUser();
			if (user != null) {
				newcomment.setUser(user);			
				newcomment.setName(user.getFullName());			
				newcomment.setApproved(user.isAdmin());
			}
			commentDAO.update(newcomment);
			userHistoryService.create(user, KConst.COMMENT, KConst.COMMENT, "Added ITEM Comment="+comment+", itemId="+item.getId());
			resetComment();
			loadComments();
			good();
		} catch (Exception e) {
			e.printStackTrace();
			bad(KConst.BAD_THING);
		}
	}
	
	public void vote(Integer score) {
		try {			
			User user = KUser.instance().getUser();
			if (user == null) {
				bad(KConst.MUST_LOGIN);
				return;
			}
			if (voted || score == null || score < 1 || score > 5) {
				bad(KConst.BAD_THING);
				return;
			}
			Vote vote = new Vote(user,item.getItem(),score);
			voteDAO.update(vote);
			userHistoryService.create(user, "Item VOTE", "Item VOTE", "Added ITEM Score="+score+", itemId="+item.getId());
			voted = true;
			resetComment();
			loadComments();
			good();
		} catch (Exception e) {
			e.printStackTrace();
			bad(KConst.BAD_THING);
		}
	}
	
	private void loadImages() {
		images = new LinkedList<KItemImage>();
		images = imageDAO.getItemImages(item.getId());
	}
	
	public boolean isPrev() {
		return prevId != null && prevId > 0;
	}
	
	public boolean isNext() {
		return nextId != null && nextId > 0;
	}

	public List<ItemColor> getColors() {
		return colors;
	}

	public List<ItemSize> getSizes() {
		return sizes;
	}

	public List<ItemMaterial> getMaterials() {
		return materials;
	}
	
	public BigDecimal getPrice() {
		return price;
	}

	public void add() {
		KUser kUser = (KUser) Component.getInstance("kUser");
		if (itemBasket == null || item == null || kUser == null || kUser.getBasket() == null) {
			bad(KConst.BAD_THING);
			return;
		}
		if ((!colors.isEmpty() && itemBasket.getItemColor() == null) 
				|| (!sizes.isEmpty() && itemBasket.getItemSize() == null)
				|| (!materials.isEmpty() && itemBasket.getItemMaterial() == null)
				|| (itemBasket.getQuantity() <= 0)) {
			bad("empty_some_selection");
			return;
		}
		Basket basket = kUser.getBasket();
		long itemColorId = itemBasket.getItemColor()==null?0:itemBasket.getItemColor().getId();
		long itemSizeId = itemBasket.getItemSize()==null?0:itemBasket.getItemSize().getId();
		long itemMaterialId = itemBasket.getItemMaterial()==null?0:itemBasket.getItemMaterial().getId();
		
		BasketItem basketItem = new BasketItem(item.getItem().getId(), itemColorId, itemSizeId, itemMaterialId, itemBasket.getQuantity());
		if (basket.getItems().contains(basketItem)) {
			for (BasketItem bi : basket.getItems()) {
				if (bi.equals(basketItem)) {
					int qnty = bi.getQuantity();
					qnty++;
					bi.setQuantity(qnty);
					break;
				}
			}
		} else {
			basket.getItems().add(basketItem);			
		}
		good();
	}
	
	public boolean isVoted() {
		return voted;
	}

	public KDataModel getCommentList() {
		return commentList;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Vote getVote() {
		return vote;
	}

	public BigDecimal getRating() {
		return rating;
	}

	public int getCurrentRating() {
		return currentRating;
	}
	
	public boolean isCurrentRatingAvb() {
		return currentRating > 0;
	}
	
	public boolean isColorAvb() {
		return !colors.isEmpty();
	}
	
	public boolean isSizeAvb() {
		return !sizes.isEmpty();
	}
	
	public boolean isMaterialAvb() {
		return !materials.isEmpty();
	}

	public KItemBasket getItemBasket() {
		return itemBasket;
	}
	
	public void selectColor(ItemColor itemColor) {
		if (itemColor == null) {
			if (log.isErrorEnabled()) {
				log.error("ItemColor is NULL");
			}
			bad(KConst.BAD_THING);
			return;
		}
		itemBasket.setItemColor(itemColor);
	}
	
	public boolean isColorSelected(ItemColor itemColor) {
		if (itemColor == null) {
			if (log.isErrorEnabled()) {
				log.error("ItemColor is NULL");
			}
			bad(KConst.BAD_THING);
			return false;
		}
		return itemBasket.getItemColor() != null && itemBasket.getItemColor().getId() == itemColor.getId();
	}
	
	public void selectSize(ItemSize itemSize) {
		if (itemSize == null) {
			if (log.isErrorEnabled()) {
				log.error("ItemColor is NULL");
			}
			bad(KConst.BAD_THING);
			return;
		}
		itemBasket.setItemSize(itemSize);
	}
	
	public boolean isSizeSelected(ItemSize itemSize) {
		if (itemSize == null) {
			if (log.isErrorEnabled()) {
				log.error("ItemColor is NULL");
			}
			bad(KConst.BAD_THING);
			return false;
		}
		return itemBasket.getItemSize() != null && itemBasket.getItemSize().getId() == itemSize.getId();
	}
	
	public boolean isUserDiscounted() {
		return userDiscount > 0;
	}
	
	public boolean isDelPrice() {
		return isUserDiscounted() || item.isDiscounted();
	}
	
	public boolean isDelDiscountPrice() {
		return isUserDiscounted();
	}

	public int getUserDiscount() {
		return userDiscount;
	}

	public Long getPrevId() {
		return prevId;
	}

	public Long getNextId() {
		return nextId;
	}
	
	public void doFavorites() {
		try {			
			User user = KUser.instance().getUser();
			if (user == null) {
				bad(KConst.MUST_LOGIN);
				return;
			}
			if (favorite) {
				UserFavorites uf = userFavoritesDAO.getFavorite(user.getId(), item.getItem().getId());
				userFavoritesDAO.delete(uf);
				favorite = false;
			} else {
				UserFavorites uf = new UserFavorites(item.getItem(), user);
				userFavoritesDAO.update(uf);			
				favorite = true;
			}
			searchFav();
			good();
		} catch (Exception e) {
			if (log.isErrorEnabled()) {
				log.error("Error on update favorite item");
			}
			bad(KConst.BAD_THING);
		}
	}

	public boolean isFavorite() {
		return favorite;
	}

	public KDataModel getFavDataModel() {
		return favDataModel;
	}

	@Override
	public void changeCurrency(Currency newc) {
		try {
			KUser kUser = KUser.instance();
			if (newc == null || kUser == null) {
				bad(KConst.BAD_THING);
				return;
			} 
			kUser.setCurrency(newc);	
			currencyId = newc.getId();
			doPriceData();
		} catch (Exception e) {
			bad(KConst.BAD_THING);
		}
		
	}
	
}
